package edu.ptu.acl.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import edu.ptu.acl.common.MyConstants;
import edu.ptu.acl.common.RequestHolder;
import edu.ptu.acl.common.ResultVO;
import edu.ptu.acl.dto.param.UserParam;
import edu.ptu.acl.entity.*;
import edu.ptu.acl.service.*;
import edu.ptu.acl.utils.MD5Util;
import edu.ptu.acl.utils.RedisUtil;
import edu.ptu.acl.utils.SnowIdWorker;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author LinJC
 * @since 2022-03-15
 */
@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    @Resource
    private IUserService userService;
    @Resource
    private IDeptService deptService;
    @Resource
    private IRoleUserService roleUserService;
    @Resource
    private IRoleService roleService;
    @Resource
    private IAclService aclService;

    @GetMapping("/getPageUser/{pageNo}/{pageSize}")
    public ResultVO getPageUser(@PathVariable("pageNo") @Min(1) int pageNo,
                                @PathVariable("pageSize") @Min(1) int pageSize){
        Page<User> page = new Page<>(pageNo, pageSize);
        userService.page(page, null);

        return ResultVO.success(page);
    }

    @GetMapping("/getUserDetail/{id}")
    public ResultVO getUserDetail(@PathVariable @NotNull(message = "id不能为空") Long id){
        User user = userService.getById(id);
        Dept dept = deptService.getById(user.getDeptId());
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("user",user);
        objectObjectHashMap.put("deptName",dept.getName());
        return ResultVO.success(objectObjectHashMap);
    }

    @GetMapping("/getCurrentUserInfo")
    public ResultVO getCurrentUserInfo(){
        User currentUser = RequestHolder.getCurrentUser();
        List<Acl> currentUserAclList = aclService.getCurrentUserAclList();
        // 所属部门  所拥有的角色  所拥有的权限
        List<String> currentUserDeptNameList = deptService.getCurrentUserDeptName(currentUser.getDeptId());
        String currentUserDeptName = currentUserDeptNameList.stream().collect(Collectors.joining("-"));
        List<Role> currentUserRoles = roleService.getCurrentUserRoles();
        String currentUserRoleName = currentUserRoles.stream().map(Role::getName).collect(Collectors.joining(","));
        String currentUserAclListName = currentUserAclList.stream().filter(acl -> StringUtils.equals(acl.getStatus(), "1"))
                .map(Acl::getName).collect(Collectors.joining(","));

        HashMap<String,Object> userInfo = new HashMap<>();
        userInfo.put("user",currentUser);
        userInfo.put("currentUserDeptName",currentUserDeptName);
        userInfo.put("currentUserRoleName",currentUserRoleName);
        userInfo.put("currentUserAclListName",currentUserAclListName);
        return ResultVO.success(userInfo);
    }

    @GetMapping("/getPageUserByCondition/{pageNo}/{pageSize}")
    public ResultVO getPageUserByCondition(User user,
                                           @PathVariable("pageNo") @Min(1) int pageNo,
                                           @PathVariable("pageSize") @Min(1) int pageSize){
        Page<User> page = new Page<>(pageNo,pageSize);
        userService.getPageUserByCondition(user,page);

        return ResultVO.success(page);
    }

    @PostMapping("/saveUser")
    public ResultVO saveUser(@RequestBody @Validated(UserParam.Save.class) UserParam userParam){
        User user = User.builder().name(userParam.getName()).email(userParam.getEmail())
                .telephone(userParam.getTelephone()).deptId(userParam.getDeptId())
                .status(MyConstants.UserState.NORMAL.getState()).build();
        user.setPassword(MD5Util.encrypt("123456"));

        if (validateUserId(userParam)!=null){
            return ResultVO.falseMessage("手机号或邮箱已被使用");
        }

        userService.save(user);
        return ResultVO.success();
    }

    @PutMapping("/updateUser")
    public ResultVO updateUser(@RequestBody @Validated(UserParam.Update.class) UserParam userParam){
        User user = User.builder().id(userParam.getId()).name(userParam.getName()).email(userParam.getEmail())
                .telephone(userParam.getTelephone()).deptId(userParam.getDeptId())
                .version(userParam.getVersion()).status(userParam.getStatus()).build();

        User existUser = validateUserId(userParam);
        if (existUser!=null && !userParam.getId().equals(existUser.getId())){
            return ResultVO.falseMessage("手机号或邮箱已被使用");
        }
        if (!userService.updateById(user)) {
            return ResultVO.fail(MyConstants.ResultCode.OPTIMISTIC_LOCKING);
        }
        offline(userParam.getId());
        return ResultVO.success();
    }

    @PutMapping("/freezeUser")
    public ResultVO updateStatus(@RequestBody @Validated(UserParam.Update.class) UserParam userParam){
        userService.updateStatus(userParam);
        return ResultVO.success();
    }

    @PutMapping("/updatePassword/{id}/{password}")
    public ResultVO updatePassword(@PathVariable @Min(value = 10000000000000000L) Long id
            ,@PathVariable @Length(min = 6,max = 16) String password){
        userService.updatePassword(id, MD5Util.encrypt(password));
        return ResultVO.success();
    }

    @DeleteMapping("/deleteUser/{id}")
    public ResultVO deleteUser(@PathVariable @Min(value = 10000000000000000L) Long id){
        userService.removeById(id);
        offline(id);
        // 删除角色用户表中该用户的记录
        QueryWrapper<RoleUser> roleUserQueryWrapper = new QueryWrapper<>();
        roleUserQueryWrapper.eq("user_id",id);
        roleUserService.remove(roleUserQueryWrapper);

        return ResultVO.success();
    }

    private void offline(Long id) {
        // 如果用户在线，强制下线
        if (RedisUtil.getValue(id.toString()) != null) {
            RedisUtil.setValue(id.toString(), "", 0);
        }
    }

    private User validateUserId(UserParam userParam) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("telephone", userParam.getTelephone()).or()
                .eq("email", userParam.getEmail());
        return userService.getOne(queryWrapper);
    }
}
